home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / cvs-1.8 / cvs-1 / cvs-1.8.1 / src / vers_ts.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-06  |  8.7 KB  |  355 lines

  1. /*
  2.  * Copyright (c) 1992, Brian Berliner and Jeff Polk
  3.  * Copyright (c) 1989-1992, Brian Berliner
  4.  * 
  5.  * You may distribute under the terms of the GNU General Public License as
  6.  * specified in the README file that comes with the CVS 1.4 kit.
  7.  */
  8.  
  9. #include "cvs.h"
  10.  
  11. #ifdef SERVER_SUPPORT
  12. static void time_stamp_server PROTO((char *, Vers_TS *));
  13. #endif
  14.  
  15. /*
  16.  * Fill in and return a Vers_TS structure "user" is the name of the local
  17.  * file; entries is the entries file - preparsed for our pleasure. rcs is
  18.  * the current source control file - preparsed for our pleasure.
  19.  */
  20. Vers_TS *
  21. Version_TS (repository, options, tag, date, user, force_tag_match,
  22.         set_time, entries, rcs)
  23.     char *repository;
  24.     char *options;
  25.     char *tag;
  26.     char *date;
  27.     char *user;
  28.     int force_tag_match;
  29.     int set_time;
  30.     List *entries;
  31.     RCSNode *rcs;
  32. {
  33.     Node *p;
  34.     RCSNode *rcsdata;
  35.     Vers_TS *vers_ts;
  36.     struct stickydirtag *sdtp;
  37.  
  38.     /* get a new Vers_TS struct */
  39.     vers_ts = (Vers_TS *) xmalloc (sizeof (Vers_TS));
  40.     memset ((char *) vers_ts, 0, sizeof (*vers_ts));
  41.  
  42.     /*
  43.      * look up the entries file entry and fill in the version and timestamp
  44.      * if entries is NULL, there is no entries file so don't bother trying to
  45.      * look it up (used by checkout -P)
  46.      */
  47.     if (entries == NULL)
  48.     {
  49.     sdtp = NULL;
  50.     p = NULL;
  51.     }
  52.     else
  53.     {
  54.     p = findnode_fn (entries, user);
  55.     sdtp = (struct stickydirtag *) entries->list->data; /* list-private */
  56.     }
  57.  
  58.     if (p != NULL)
  59.     {
  60.     Entnode *entdata = (Entnode *) p->data;
  61.  
  62.     vers_ts->vn_user = xstrdup (entdata->version);
  63.     vers_ts->ts_rcs = xstrdup (entdata->timestamp);
  64.     vers_ts->ts_conflict = xstrdup (entdata->conflict);
  65.     if (!tag)
  66.     {
  67.         if (!(sdtp && sdtp->aflag))
  68.         vers_ts->tag = xstrdup (entdata->tag);
  69.     }
  70.     if (!date)
  71.     {
  72.         if (!(sdtp && sdtp->aflag))
  73.         vers_ts->date = xstrdup (entdata->date);
  74.     }
  75.     if (!options || (options && *options == '\0'))
  76.     {
  77.         if (!(sdtp && sdtp->aflag))
  78.         vers_ts->options = xstrdup (entdata->options);
  79.     }
  80.     vers_ts->entdata = entdata;
  81.     }
  82.  
  83.     /*
  84.      * -k options specified on the command line override (and overwrite)
  85.      * options stored in the entries file
  86.      */
  87.     if (options)
  88.     vers_ts->options = xstrdup (options);
  89.     else if (!vers_ts->options)
  90.     {
  91.     if (sdtp && sdtp->aflag == 0)
  92.         vers_ts->options = xstrdup (sdtp->options);
  93.     else if (rcs != NULL)
  94.     {
  95.         /* If no keyword expansion was specified on command line,
  96.            use whatever was in the rcs file (if there is one).  This
  97.            is how we, if we are the server, tell the client whether
  98.            a file is binary.  */
  99.         char *rcsexpand = RCS_getexpand (rcs);
  100.         if (rcsexpand != NULL)
  101.         {
  102.         vers_ts->options = xmalloc (strlen (rcsexpand) + 3);
  103.         strcpy (vers_ts->options, "-k");
  104.         strcat (vers_ts->options, rcsexpand);
  105.         }
  106.     }
  107.     }
  108.     if (!vers_ts->options)
  109.     vers_ts->options = xstrdup ("");
  110.  
  111.     /*
  112.      * if tags were specified on the command line, they override what is in
  113.      * the Entries file
  114.      */
  115.     if (tag || date)
  116.     {
  117.     vers_ts->tag = xstrdup (tag);
  118.     vers_ts->date = xstrdup (date);
  119.     }
  120.     else if (!vers_ts->entdata && (sdtp && sdtp->aflag == 0))
  121.     {
  122.     if (!vers_ts->tag)
  123.         vers_ts->tag = xstrdup (sdtp->tag);
  124.     if (!vers_ts->date)
  125.         vers_ts->date = xstrdup (sdtp->date);
  126.     }
  127.  
  128.     /* Now look up the info on the source controlled file */
  129.     if (rcs != NULL)
  130.     {
  131.     rcsdata = rcs;
  132.     rcsdata->refcount++;
  133.     }
  134.     else if (repository != NULL)
  135.     rcsdata = RCS_parse (user, repository);
  136.     else
  137.     rcsdata = NULL;
  138.  
  139.     if (rcsdata != NULL)
  140.     {
  141.     /* squirrel away the rcsdata pointer for others */
  142.     vers_ts->srcfile = rcsdata;
  143.  
  144.     if (vers_ts->tag && strcmp (vers_ts->tag, TAG_BASE) == 0)
  145.     {
  146.         vers_ts->vn_rcs = xstrdup (vers_ts->vn_user);
  147.         vers_ts->vn_tag = xstrdup (vers_ts->vn_user);
  148.     }
  149.     else
  150.     {
  151.         vers_ts->vn_rcs = RCS_getversion (rcsdata, vers_ts->tag,
  152.                     vers_ts->date, force_tag_match, 1);
  153.         if (vers_ts->vn_rcs == NULL)
  154.         vers_ts->vn_tag = NULL;
  155.         else
  156.         {
  157.         char *colon = strchr (vers_ts->vn_rcs, ':');
  158.         if (colon)
  159.         {
  160.             vers_ts->vn_tag = xstrdup (colon+1);
  161.             *colon = '\0';
  162.         }
  163.         else
  164.             vers_ts->vn_tag = xstrdup (vers_ts->vn_rcs);
  165.         }
  166.     }
  167.  
  168.     /*
  169.      * If the source control file exists and has the requested revision,
  170.      * get the Date the revision was checked in.  If "user" exists, set
  171.      * its mtime.
  172.      */
  173.     if (set_time)
  174.     {
  175.         struct utimbuf t;
  176.  
  177.         memset ((char *) &t, 0, sizeof (t));
  178.         if (vers_ts->vn_rcs &&
  179.         (t.actime = t.modtime = RCS_getrevtime (rcsdata,
  180.          vers_ts->vn_rcs, (char *) 0, 0)) != -1)
  181.         (void) utime (user, &t);
  182.     }
  183.     }
  184.  
  185.     /* get user file time-stamp in ts_user */
  186.     if (entries != (List *) NULL)
  187.     {
  188. #ifdef SERVER_SUPPORT
  189.     if (server_active)
  190.         time_stamp_server (user, vers_ts);
  191.     else
  192. #endif
  193.         vers_ts->ts_user = time_stamp (user);
  194.     }
  195.  
  196.     return (vers_ts);
  197. }
  198.  
  199. #ifdef SERVER_SUPPORT
  200.  
  201. /* Set VERS_TS->TS_USER to time stamp for FILE.  */
  202.  
  203. /* Separate these out to keep the logic below clearer.  */
  204. #define mark_lost(V)        ((V)->ts_user = 0)
  205. #define mark_unchanged(V)    ((V)->ts_user = xstrdup ((V)->ts_rcs))
  206.  
  207. static void
  208. time_stamp_server (file, vers_ts)
  209.     char *file;
  210.     Vers_TS *vers_ts;
  211. {
  212.     struct stat sb;
  213.     char *cp;
  214.  
  215.     if (stat (file, &sb) < 0)
  216.     {
  217.     if (! existence_error (errno))
  218.         error (1, errno, "cannot stat temp file");
  219.     if (use_unchanged)
  220.       {
  221.         /* Missing file means lost or unmodified; check entries
  222.            file to see which.
  223.  
  224.            XXX FIXME - If there's no entries file line, we
  225.            wouldn't be getting the file at all, so consider it
  226.            lost.  I don't know that that's right, but it's not
  227.            clear to me that either choice is.  Besides, would we
  228.            have an RCS string in that case anyways?  */
  229.         if (vers_ts->entdata == NULL)
  230.           mark_lost (vers_ts);
  231.         else if (vers_ts->entdata->timestamp
  232.              && vers_ts->entdata->timestamp[0] == '=')
  233.           mark_unchanged (vers_ts);
  234.         else
  235.           mark_lost (vers_ts);
  236.       }
  237.     else
  238.       {
  239.         /* Missing file in the temp directory means that the file
  240.            was not modified.  */
  241.         mark_unchanged (vers_ts);
  242.       }
  243.     }
  244.     else if (sb.st_mtime == 0)
  245.     {
  246.     if (use_unchanged)
  247.       /* We shouldn't reach this case any more!  */
  248.       abort ();
  249.  
  250.     /* Special code used by server.c to indicate the file was lost.  */
  251.     mark_lost (vers_ts);
  252.     }
  253.     else
  254.     {
  255.         struct tm *tm_p;
  256.         struct tm local_tm;
  257.  
  258.     vers_ts->ts_user = xmalloc (25);
  259.     /* We want to use the same timestamp format as is stored in the
  260.        st_mtime.  For unix (and NT I think) this *must* be universal
  261.        time (UT), so that files don't appear to be modified merely
  262.        because the timezone has changed.  For VMS, or hopefully other
  263.        systems where gmtime returns NULL, the modification time is
  264.        stored in local time, and therefore it is not possible to cause
  265.        st_mtime to be out of sync by changing the timezone.  */
  266.     tm_p = gmtime (&sb.st_mtime);
  267.     if (tm_p)
  268.     {
  269.         memcpy (&local_tm, tm_p, sizeof (local_tm));
  270.         cp = asctime (&local_tm);    /* copy in the modify time */
  271.     }
  272.     else
  273.         cp = ctime (&sb.st_mtime);
  274.  
  275.     cp[24] = 0;
  276.     (void) strcpy (vers_ts->ts_user, cp);
  277.     }
  278. }
  279.  
  280. #endif /* SERVER_SUPPORT */
  281. /*
  282.  * Gets the time-stamp for the file "file" and returns it in space it
  283.  * allocates
  284.  */
  285. char *
  286. time_stamp (file)
  287.     char *file;
  288. {
  289.     struct stat sb;
  290.     char *cp;
  291.     char *ts;
  292.  
  293.     if (stat (file, &sb) < 0)
  294.     {
  295.     ts = NULL;
  296.     }
  297.     else
  298.     {
  299.     struct tm *tm_p;
  300.         struct tm local_tm;
  301.     ts = xmalloc (25);
  302.     /* We want to use the same timestamp format as is stored in the
  303.        st_mtime.  For unix (and NT I think) this *must* be universal
  304.        time (UT), so that files don't appear to be modified merely
  305.        because the timezone has changed.  For VMS, or hopefully other
  306.        systems where gmtime returns NULL, the modification time is
  307.        stored in local time, and therefore it is not possible to cause
  308.        st_mtime to be out of sync by changing the timezone.  */
  309.     tm_p = gmtime (&sb.st_mtime);
  310.     if (tm_p)
  311.     {
  312.         memcpy (&local_tm, tm_p, sizeof (local_tm));
  313.         cp = asctime (&local_tm);    /* copy in the modify time */
  314.     }
  315.     else
  316.         cp = ctime(&sb.st_mtime);
  317.  
  318.     cp[24] = 0;
  319.     (void) strcpy (ts, cp);
  320.     }
  321.  
  322.     return (ts);
  323. }
  324.  
  325. /*
  326.  * free up a Vers_TS struct
  327.  */
  328. void
  329. freevers_ts (versp)
  330.     Vers_TS **versp;
  331. {
  332.     if ((*versp)->srcfile)
  333.     freercsnode (&((*versp)->srcfile));
  334.     if ((*versp)->vn_user)
  335.     free ((*versp)->vn_user);
  336.     if ((*versp)->vn_rcs)
  337.     free ((*versp)->vn_rcs);
  338.     if ((*versp)->vn_tag)
  339.     free ((*versp)->vn_tag);
  340.     if ((*versp)->ts_user)
  341.     free ((*versp)->ts_user);
  342.     if ((*versp)->ts_rcs)
  343.     free ((*versp)->ts_rcs);
  344.     if ((*versp)->options)
  345.     free ((*versp)->options);
  346.     if ((*versp)->tag)
  347.     free ((*versp)->tag);
  348.     if ((*versp)->date)
  349.     free ((*versp)->date);
  350.     if ((*versp)->ts_conflict)
  351.     free ((*versp)->ts_conflict);
  352.     free ((char *) *versp);
  353.     *versp = (Vers_TS *) NULL;
  354. }
  355.